package com.zhihuitong.meeting.net;

import android.app.Application;
import android.content.Context;
import android.support.annotation.Nullable;
import android.text.TextUtils;

import com.google.gson.Gson;
import com.lzy.okgo.OkGo;
import com.lzy.okgo.cookie.CookieJarImpl;
import com.lzy.okgo.cookie.store.MemoryCookieStore;
import com.lzy.okgo.https.HttpsUtils;
import com.lzy.okgo.interceptor.HttpLoggingInterceptor;
import com.lzy.okgo.model.HttpParams;
import com.lzy.okgo.request.GetRequest;
import com.lzy.okgo.request.PostRequest;
import com.zhihuitong.meeting.BuildConfig;

import java.io.File;
import java.net.FileNameMap;
import java.net.URLConnection;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;

import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.RequestBody;

/**
 * 作者： guoyuan
 * 时间 2017/8/22.
 * 文件描述：网络请求封装
 * 版本号：V 1.0
 **/

public class HttpUtil {
    public static final long DEFAULT_MILLISECONDS = 10000;      //默认的超时时间
    public static int RETRY_COUNT = 1;                      //失败重连次数,实际连接次数会比该值大1(一次原始请求，2次重连请求)
    public static long REFRESH_TIME = 300;                      //回调刷新时间（单位ms）

    public static void init(Context context) {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        //log相关
        if (BuildConfig.DEBUG) {
            HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor("OkGo");
            loggingInterceptor.setPrintLevel(HttpLoggingInterceptor.Level.BODY);        //log打印级别，决定了log显示的详细程度
            loggingInterceptor.setColorLevel(Level.INFO);                               //log颜色级别，决定了log在控制台显示的颜色
            //添加OkGo默认debug日志
            builder.addInterceptor(loggingInterceptor);
        }

        //超时时间设置，默认60秒
        builder.readTimeout(DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS);      //全局的读取超时时间
        builder.writeTimeout(DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS);     //全局的写入超时时间
        builder.connectTimeout(DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS);   //全局的连接超时时间
        builder.cookieJar(new CookieJarImpl(new MemoryCookieStore()));
        //测试环境：信任所有证书,不安全有风险
        if (BuildConfig.DEBUG) {
            HttpsUtils.SSLParams sslParams1 = HttpsUtils.getSslSocketFactory();
            builder.sslSocketFactory(sslParams1.sSLSocketFactory, sslParams1.trustManager);
            builder.hostnameVerifier(new SafeHostnameVerifier());
        }

        // 其他统一的配置
        // 详细说明看GitHub文档：https://github.com/jeasonlzy/
        OkGo.getInstance().init((Application) context)                           //必须调用初始化
                .setOkHttpClient(builder.build())               //建议设置OkHttpClient，不设置会使用默认的
                // .setCacheMode(CacheMode.NO_CACHE)               //全局统一缓存模式，默认不使用缓存，可以不传
                //.setCacheTime(CacheEntity.CACHE_NEVER_EXPIRE)   //全局统一缓存时间，默认永不过期，可以不传
                .setRetryCount(RETRY_COUNT);                           //全局统一超时重连次数，默认为三次，那么最差的情况会请求4次(一次原始请求，三次重连请求)，不需要可以设置为0

    }

    /**
     * 证书校验规则
     */
    private static class SafeHostnameVerifier implements HostnameVerifier {
        @Override
        public boolean verify(String hostname, SSLSession session) {
            //验证主机名是否匹配
            return true;
        }
    }

    /**
     * 基本post请求,不需要带时间戳
     *
     * @param url    请求的url
     * @param params 请求的参数
     * @param <T>    回调泛型,必传
     * @return
     */
    public static <T> PostRequest<T> post(String url, HttpParams params, @Nullable String tag) {
        return OkGo.<T>post(url).params(params).tag(TextUtils.isEmpty(tag) ? url : tag);
    }

    /**
     * 基本post请求不带url验证
     *
     * @param url        请求的url
     * @param requestObj 请求的参数
     * @param <T>        回调泛型,必传
     * @return
     */
    public static <T> PostRequest<T> post(String url, Object requestObj, @Nullable String tag) {
       Gson gson = new Gson();
      //  Gson gson = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
        String json = gson.toJson(requestObj);
        RequestBody body = RequestBody.create(MediaType.parse("application/json"), json);
        return OkGo.<T>post(url).upRequestBody(body).tag(TextUtils.isEmpty(tag) ? url : tag);
    }

    /**
     * 基本get请求,不需要带时间戳
     *
     * @param url 请求的url
     * @param <T> 回调泛型,必传
     * @return
     */
    public static <T> GetRequest<T> get(String url, HttpParams params, @Nullable String tag) {
        return OkGo.<T>get(url).params(params).tag(TextUtils.isEmpty(tag) ? url : tag);
    }


    /**
     * 上传文件(RequestBody)
     *
     * @param url       请求url
     * @param fileNames 文件集合
     * @param <T>       回调数据类型,必传
     * @return
     */
    @Deprecated
    public static <T> PostRequest<T> postFiles(String url, List<String> fileNames) {
        RequestBody requestBody = getRequestBody(fileNames);
        return OkGo.<T>post(url).upRequestBody(requestBody).tag(url);
    }


    /**
     * 获取文件MimeType
     *
     * @param filename
     * @return
     */
    private static String getMimeType(String filename) {
        FileNameMap filenameMap = URLConnection.getFileNameMap();
        String contentType = filenameMap.getContentTypeFor(filename);
        if (contentType == null) {
            contentType = "application/octet-stream"; //* exe,所有的可执行程序
        }
        return contentType;
    }

    /**
     * 通过上传的文件的完整路径生成RequestBody
     *
     * @param fileNames 完整的文件路径
     * @return
     */
    private static RequestBody getRequestBody(List<String> fileNames) {
        //创建MultipartBody.Builder，用于添加请求的数据
        MultipartBody.Builder builder = new MultipartBody.Builder();
        for (int i = 0; i < fileNames.size(); i++) { //对文件进行遍历
            File file = new File(fileNames.get(i)); //生成文件
            //根据文件的后缀名，获得文件类型
            String fileType = getMimeType(file.getName());
            builder.addFormDataPart( //给Builder添加上传的文件
                    "uploadFile",  //请求的名字
                    file.getName(), //文件的文字，服务器端用来解析的
                    RequestBody.create(MediaType.parse(fileType), file) //创建RequestBody，把上传的文件放入
            );
        }
        return builder.build(); //根据Builder创建请求
    }


    /**
     * 根据Tag取消请求
     */
    public static void cancelTag(Object tag) {
        OkGo.getInstance().cancelTag(tag);
    }
}
